package com.agrimall.websocket;

import com.agrimall.entity.ChatMessage;
import com.agrimall.entity.ConsultationSession;
import com.agrimall.mapper.ChatMessageMapper;
import com.agrimall.mapper.ConsultationSessionMapper;
import com.agrimall.util.MyBatisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.session.SqlSession;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 聊天WebSocket服务器端
 */
@ServerEndpoint("/chat/{userId}/{userType}/{sessionId}")
public class ChatWebSocket {
    // 存储所有连接的WebSocket会话，key为sessionId，value为Session对象
    private static final Map<String, Session> sessions = new ConcurrentHashMap<>();
    
    // 存储用户ID和Session的映射关系，用于快速查找
    private static final Map<String, Session> userSessions = new ConcurrentHashMap<>();
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    private String currentSessionId;
    private Long currentUserId;
    private Integer currentUserType;
    
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, 
                      @PathParam("userId") String userId,
                      @PathParam("userType") String userType,
                      @PathParam("sessionId") String sessionId) {
        this.currentSessionId = sessionId;
        this.currentUserId = Long.parseLong(userId);
        this.currentUserType = Integer.parseInt(userType);
        
        // 存储会话
        String userKey = userId + "_" + userType + "_" + sessionId;
        sessions.put(sessionId, session);
        userSessions.put(userKey, session);
        
        System.out.println("WebSocket连接建立: userId=" + userId + ", userType=" + userType + ", sessionId=" + sessionId);
        
        // 发送连接成功消息
        try {
            Map<String, Object> message = new java.util.HashMap<>();
            message.put("type", "connected");
            message.put("message", "连接成功");
            session.getBasicRemote().sendText(objectMapper.writeValueAsString(message));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String messageJson, Session session) {
        try {
            // 解析消息
            Map<String, Object> messageMap = objectMapper.readValue(messageJson, Map.class);
            String type = (String) messageMap.get("type");
            String content = (String) messageMap.get("content");
            Long productId = messageMap.get("productId") != null ? 
                Long.parseLong(messageMap.get("productId").toString()) : null;
            String productName = (String) messageMap.get("productName");
            
            if ("message".equals(type)) {
                // 保存消息到数据库
                ChatMessage chatMessage = new ChatMessage();
                chatMessage.setSessionId(currentSessionId);
                chatMessage.setSenderId(currentUserId);
                chatMessage.setSenderType(currentUserType);
                chatMessage.setReceiverId(getReceiverId());
                chatMessage.setReceiverType(1 - currentUserType); // 接收者类型与发送者相反
                chatMessage.setProductId(productId);
                chatMessage.setProductName(productName);
                chatMessage.setContent(content);
                chatMessage.setMessageType(0); // 文本消息
                chatMessage.setCreateTime(new Date());
                
                saveMessage(chatMessage);
                
                // 更新会话信息
                updateSession(chatMessage);
                
                // 发送消息给接收者
                sendMessageToReceiver(chatMessage);
                
                // 发送确认消息给发送者
                Map<String, Object> ackMessage = new java.util.HashMap<>();
                ackMessage.put("type", "ack");
                ackMessage.put("messageId", chatMessage.getMessageId());
                ackMessage.put("status", "success");
                session.getBasicRemote().sendText(objectMapper.writeValueAsString(ackMessage));
            }
        } catch (Exception e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMessage = new java.util.HashMap<>();
                errorMessage.put("type", "error");
                errorMessage.put("message", "消息处理失败：" + e.getMessage());
                session.getBasicRemote().sendText(objectMapper.writeValueAsString(errorMessage));
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }
    
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        String userKey = currentUserId + "_" + currentUserType + "_" + currentSessionId;
        sessions.remove(currentSessionId);
        userSessions.remove(userKey);
        System.out.println("WebSocket连接关闭: sessionId=" + currentSessionId);
    }
    
    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
        String userKey = currentUserId + "_" + currentUserType + "_" + currentSessionId;
        sessions.remove(currentSessionId);
        userSessions.remove(userKey);
    }
    
    /**
     * 获取接收者ID
     */
    private Long getReceiverId() {
        // 从sessionId中解析接收者ID
        // sessionId格式：userId_merchantId_productId
        String[] parts = currentSessionId.split("_");
        if (currentUserType == 0) {
            // 用户发送，接收者是商家
            return Long.parseLong(parts[1]);
        } else {
            // 商家发送，接收者是用户
            return Long.parseLong(parts[0]);
        }
    }
    
    /**
     * 保存消息到数据库
     */
    private void saveMessage(ChatMessage message) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            ChatMessageMapper mapper = sqlSession.getMapper(ChatMessageMapper.class);
            mapper.insert(message);
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
            throw new RuntimeException("保存消息失败", e);
        } finally {
            sqlSession.close();
        }
    }
    
    /**
     * 更新会话信息
     */
    private void updateSession(ChatMessage message) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            ConsultationSessionMapper mapper = sqlSession.getMapper(ConsultationSessionMapper.class);
            
            // 从sessionId解析信息
            String[] parts = message.getSessionId().split("_");
            Long userId = Long.parseLong(parts[0]);
            Long merchantId = Long.parseLong(parts[1]);
            
            ConsultationSession session = new ConsultationSession();
            session.setSessionId(message.getSessionId());
            session.setUserId(userId);
            session.setMerchantId(merchantId);
            session.setProductId(message.getProductId());
            session.setProductName(message.getProductName());
            session.setLastMessage(message.getContent());
            session.setLastMessageTime(message.getCreateTime());
            
            // 更新未读消息数
            if (message.getSenderType() == 0) {
                // 用户发送，商家未读数+1
                session.setUnreadCountUser(0);
                session.setUnreadCountMerchant(1);
            } else {
                // 商家发送，用户未读数+1
                session.setUnreadCountUser(1);
                session.setUnreadCountMerchant(0);
            }
            
            mapper.insertOrUpdate(session);
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
    }
    
    /**
     * 发送消息给接收者
     */
    private void sendMessageToReceiver(ChatMessage message) {
        try {
            // 构建接收者的key
            Long receiverId = getReceiverId();
            Integer receiverType = 1 - currentUserType;
            String receiverKey = receiverId + "_" + receiverType + "_" + currentSessionId;
            
            Session receiverSession = userSessions.get(receiverKey);
            if (receiverSession != null && receiverSession.isOpen()) {
                // 构建消息对象
                Map<String, Object> messageMap = new java.util.HashMap<>();
                messageMap.put("type", "message");
                messageMap.put("messageId", message.getMessageId());
                messageMap.put("senderId", message.getSenderId());
                messageMap.put("senderType", message.getSenderType());
                messageMap.put("content", message.getContent());
                messageMap.put("productId", message.getProductId());
                messageMap.put("productName", message.getProductName());
                messageMap.put("createTime", message.getCreateTime().getTime());
                
                receiverSession.getBasicRemote().sendText(objectMapper.writeValueAsString(messageMap));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 获取会话列表（用于查询历史消息）
     */
    public static Session getSession(String sessionId) {
        return sessions.get(sessionId);
    }
}




